﻿namespace SandScript
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using Models;
    using Newtonsoft.Json;
    using Ninject;
    using Wrappers;

    public class Builder : IBuilder
    {
        private const string StartJsonDelimiter = "#_#Begin#_#";
        private const string EndJsonDelimiter = "#_#End#_#";

        private readonly IProcessHelper processHelper;
        private readonly IFileSystemWrapper fileSystemWrapper;
        private readonly IContextBuilder contextBuilder;

        public Builder(IProcessHelper processHelper, IFileSystemWrapper fileSystemWrapper, IContextBuilder contextBuilder)
        {
            this.processHelper = processHelper;
            this.fileSystemWrapper = fileSystemWrapper;
            this.contextBuilder = contextBuilder;
        }

        public static IBuilder Create()
        {
            return Kernel.Root.Get<IBuilder>();
        }

        public void BuildReflection(string filePath, params string[] namespaces)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                throw new ArgumentNullException("filePath");
            }

            if (!this.fileSystemWrapper.FileExists(filePath))
            {
                throw new ArgumentException("The given file could not be found.", "filePath");
            }

            switch (Path.GetExtension(filePath).ToLower())
            {
                case ".htm":
                case ".html":
                    var contextPath = this.contextBuilder.CreateContext(filePath);
                    var output = this.ProcessContext(contextPath);
                    var data = JsonConvert.DeserializeObject<IList<MemberDetail>>(output);

                    break;
                case ".js":
                    break;
                default:
                    throw new ArgumentException("The given path must be a HTML or JS file.", "filePath");
            }
        }

        private string ProcessContext(string contextPath)
        {
            string phantomPath;

            if (this.fileSystemWrapper.TryResolvePath("phantomjs.exe", out phantomPath))
            {
                var arguments = string.Concat(@"sandScript.phantom.js ""file:///", contextPath.Replace('\\', '/'), '"');
                var output = this.processHelper.RunExecutableAndCaptureOutput(phantomPath, arguments);

                if (!string.IsNullOrEmpty(output.StandardOutput))
                {
                    var json = output.StandardOutput;
                    var startIndex = json.IndexOf(StartJsonDelimiter);
                    var endIndex = json.IndexOf(EndJsonDelimiter);

                    if (startIndex >= 0)
                    {
                        startIndex += StartJsonDelimiter.Length;
                        json = json.Substring(startIndex, endIndex - startIndex).Trim();
                    }

                    return json;
                }
            }

            return string.Empty;
        }
    }
}
